package com.ruoyi.common.utils;

import cn.hutool.core.lang.Dict;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Slf4j
public class JsonUtil {
    private static final ObjectMapper MAPPER = new ObjectMapper();

    static {
        // 序列化结果格式化
        //     MAPPER.enable(SerializationFeature.INDENT_OUTPUT);
        // 对于空的对象转json的时候不抛出错误
        MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 解决实体未包含字段反序列化时抛出异常
        MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 反序列化时，空字符串对于的实例属性为null
        MAPPER.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        // 允许C和C++样式注释
        MAPPER.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        // 允许属性名称没有引号
        MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 允许单引号
        MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        MAPPER.registerModule(new JavaTimeModule()).registerModule(new ParameterNamesModule()).registerModule(new Jdk8Module());
        MAPPER.findAndRegisterModules();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        MAPPER.setDateFormat(dateFormat);
    }


    /**
     * 将一个object转换为json, 可以是一个java对象，也可以使集合
     *
     * @param obj - 传入的数据
     */
    public static String objectToJson(Object obj) {
        String json = "";
        try {
            json = MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("objectToJson失败", e);
        }
        return json;
    }

    /**
     * 将json结果集转化为对象
     *
     * @param json     - json数据
     * @param beanType - 转换的实体类型
     */
    public static <T> T jsonToClass(String json, Class<T> beanType) {
        T t = null;
        try {
            t = MAPPER.readValue(json, beanType);
        } catch (Exception e) {
            log.error("jsonToClass失败", e);
        }
        return t;
    }

    /**
     * 将json结果集转化为对象
     *
     * @param json         - json数据
     * @param valueTypeRef - 转换的实体类型
     */
    public static <T> T jsonToClass(String json, TypeReference<T> valueTypeRef) {
        T t = null;
        try {
            t = MAPPER.readValue(json, valueTypeRef);
        } catch (Exception e) {
            log.error("jsonToClass失败", e);
        }
        return t;
    }

    /**
     * 将json数据转换成Map
     *
     * @param json - 转换的数据
     */
    public static <K, V> Map<K, V> jsonToMap(String json) {
        Map<K, V> map = Collections.emptyMap();
        try {
            map = MAPPER.readValue(json, new TypeReference<Map<K, V>>() {
            });
        } catch (Exception e) {
            log.error("jsonToMap失败", e);
        }
        return map;
    }

    /**
     * 将json数据转换成Dict
     *
     * @param json - 转换的数据
     */
    public static Dict jsonToDict(String json) {
        Dict dict = new Dict();
        try {
            dict = MAPPER.readValue(json, new TypeReference<Dict>() {
            });
        } catch (Exception e) {
            log.error("jsonToDict失败", e);
        }
        return dict;
    }

    /**
     * 将json数据转换成list
     *
     * @param json - 转换的数据
     */
    public static <T> List<T> jsonToList(String json, Class<T> beanType) {
        List<T> list = new ArrayList<>();
        try {
            JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
            list = MAPPER.readValue(json, javaType);
        } catch (Exception e) {
            log.error("jsonToList失败", e);
        }
        return list;
    }

    /**
     * 将json结果jsonNode
     */
    public static JsonNode parseJson(String jsonData) {
        try {
            return MAPPER.readTree(jsonData);
        } catch (Exception e) {
            log.error("parseJson失败", e);
            throw new RuntimeException("parseJson失败", e);
        }
    }
}

